#include <stdio.h>
#include <stdlib.h>
#include "bool.h"
#include "tables.h"

void BitsCopy(bool* DatOut, bool* DatIn, int Len);

void ByteToBit(bool* DatOut, char* DatIn, int Num);

void BitToByte(char* DatOut, bool* DatIn, int Num);

void BitToHex(char* DatOut, bool* DatIn, int Num);

void HexToBit(bool* DatOut, char* DatIn, int Num);

// 位置置换函数
void TablePermute(bool* DatOut, bool* DatIn, const char* Table, int Num);

// 循环左移Len长度Num移动位数
void LoopMove(bool* DataIn, int Len, int Num);

// 抑或
void Xor(bool* DatA, bool* DataB, int Num);

void S_Change(bool DatOut[32], bool DatIn[48]);


void F_Change(bool DatIn[32], bool DatKi[48]);

void SetKey(char KeyIn[8]);

void PlayDes(char MesOut[8], char MesIn[8]);

void KickDes(char MesOut[8], char MesIn[8]);

int main(void)
{
	int i = 0;
	char MesHex[16] = { 0 };
	char MyKey[8] = { 0 };
	char YourKey[8] = { 0 };
	char MyMessage[8] = { 0 };
	char DecryptMessage[8] = { 0 };

	printf("Welcome! Please input your Message (64 bit):");
	gets(MyMessage);

	printf("Please input your secret key:");
	gets(MyKey);

	while (MyKey[i] != '\0')
	{
		i++;
	}

	while (i != 8)
	{
		printf("Please input a correct Secret Key!");
		gets(MyKey);
		i = 0;
		while (MyKey[i] != '\0')
		{
			i++;
		}
	}

	SetKey(MyKey);

	PlayDes(MesHex, MyMessage);

	printf("Your Message is Encrypted!:");
	for (i = 0; i < 16; i++)
	{
		printf("%c", MesHex[i]);
	}

	printf("\n");

	SetKey(MyKey);
	KickDes(DecryptMessage, MesHex);
	printf("Deciphering Over!!!:");
	for (i = 0; i < 8; i++)
	{
		printf("%c", DecryptMessage[i]);
	}

	printf("\n");
	return 0;
}


void BitsCopy(bool* DatOut, bool* DatIn, int Len)
{
	int i = 0;
	for (i = 0; i < Len; i++)
	{
		DatOut[i] = DatIn[i];
	}
}

void ByteToBit(bool* DatOut, char* DatIn, int Num)
{
	int i = 0;
	for (i = 0; i < Num; i++)
	{
		DatOut[i] = (DatIn[i / 8] >> (i % 8)) & 0x01;
	}
}

void BitToByte(char* DatOut, bool* DatIn, int Num)
{
	int i = 0;
	for (i = 0; i < (Num / 8); i++)
	{
		DatOut[i] = 0;
	}
	for (i = 0; i < Num; i++)
	{
		DatOut[i / 8] |= DatIn[i] << (i % 8);
	}
}

void BitToHex(char* DatOut, bool* DatIn, int Num)
{
	int i = 0;
	for (i = 0; i < Num / 4; i++)
	{
		DatOut[i] = 0;
	}
	for (i = 0; i < Num / 4; i++)
	{
		DatOut[i] = DatIn[i * 4] + (DatIn[i * 4 + 1] << 1) + \
			(DatIn[i * 4 + 2] << 2) + (DatIn[i * 4 + 3] << 3);
		if ((DatOut[i] % 16) > 9)
		{
			DatOut[i] = DatOut[i] % 16 + '7';
		}
		else
		{
			DatOut[i] = DatOut[i] % 16 + '0';
		}
	}
}

void HexToBit(bool* DatOut, char* DatIn, int Num)
{
	int i = 0; // 字符型输入
	for (i = 0;i < Num; i++)
	{
		if ((DatIn[i / 4]) > '9')  // 大于9
		{
			DatOut[i] = ((DatIn[i / 4] - '7') >> (i % 4)) & 0x01;
		}
		else
		{
			DatOut[i] = ((DatIn[i / 4] - '0') >> (i % 4)) & 0x01;
		}
	}
}


void TablePermute(bool* DatOut, bool* DatIn, const char* Table, int Num)
{
	int i = 0;
	static bool Temp[256] = { 0 };

	for (i = 0;i < Num;i++)  // Num为置换的长度
	{
		Temp[i] = DatIn[Table[i] - 1]; // 原来的数据按对应的表上的位置排列

	}

	BitsCopy(DatOut, Temp, Num); // 把缓存Temp的值输出
}

void LoopMove(bool* DatIn, int Len, int Num) // 循环左移 Len数据长度 Num移动位数
{
	static bool Temp[256] = { 0 };
	BitsCopy(Temp, DatIn, Num); // 将数据最左边的Num位(被移出去的)存入Temp
	BitsCopy(DatIn, DatIn + Num, Len - Num); // 将数据左边开始的第Num移入原来的空间
	BitsCopy(DatIn + Len - Num, Temp, Num); // 将缓存中移出去的数据加到最右边
}

void Xor(bool* DatA, bool* DatB, int Num) // 异或函数
{
	int i = 0;
	for (i = 0; i < Num; i++)
	{
		DatA[i] = DatA[i] ^ DatB[i];
	}

}

void S_Change(bool DatOut[32], bool DatIn[48]) // S盒变换
{
	int i, X, Y; // i为8个S盒
	for(i = 0, Y = 0, X = 0; i < 8; i++, DatIn += 6, DatOut += 4) // 每执行一次，输入数据偏移6位
	{
		Y = (DatIn[0] << 1) + DatIn[5];
		X = (DatIn[1] << 3) + (DatIn[2] << 2) + (DatIn[3] << 1) + DatIn[4];
		ByteToBit(DatOut, &S_Box[i][Y][X], 4);
	}
}

void F_Change(bool DatIn[32], bool DatKi[48])
{
	static bool MiR[48] = {0}; // 输入32位通过E选位变为48位
	TablePermute(MiR, DatIn, E_Table, 48);
	Xor(MiR, DatKi, 48); // 和子密钥异或
	S_Change(DatIn, MiR); // S盒变换
	TablePermute(DatIn, DatIn, P_Table, 32); // P置换后输出
}


void SetKey(char KeyIn[8]) // 设置密钥 获取子密钥Ki
{
	int i = 0;
	static bool KeyBit[64] = { 0 }; // 密钥二进制存储空间
	static bool* KiL = &KeyBit[0], * KiR = &KeyBit[28]; // 前28, 后28共56
	ByteToBit(KeyBit, KeyIn, 64); // 把密钥转为二进制存入KeyBit
	TablePermute(KeyBit, KeyBit, PC1_Table, 56); // PC1表置换 56次
	for (i = 0;i<16;i++)
	{
		LoopMove(KiL, 28, Move_Table[i]); // 前28位左移
		LoopMove(KiR, 28, Move_Table[i]); // 后28位左移
		TablePermute(SubKey[i], KeyBit, PC2_Table, 48);
		// 二维数组 SubKey[i]为每一行起始地址
		// 每移一次位进行PC2置换得 Ki 48位
	}
}


void PlayDes(char MesOut[8], char MesIn[8]) // 执行DES加密
{ // 字节输入 Bin运算 Hex输出
	int i = 0;
	static bool MesBit[64] = { 0 }; // 明文二进制存储空间 64位
	static bool Temp[32] = { 0 };
	static bool* MiL = &MesBit[0], * MiR = &MesBit[32]; // 前32位 后32位
	ByteToBit(MesBit, MesIn, 64); // 把明文换成二进制存入MesBit
	TablePermute(MesBit, MesBit, IP_Table, 64); // IP置换
	for (i = 0;i<16;i++) // 迭代16次
	{
		BitsCopy(Temp, MiR, 32); // 临时存储
		F_Change(MiR, SubKey[i]); // F函数变换
		Xor(MiR, MiL, 32); // 得到Ri
		BitsCopy(MiL, Temp, 32); // 得到Li
	}
	TablePermute(MesBit, MesBit, IPR_Table, 64);
	BitToHex(MesOut, MesBit, 64);
}


void KickDes(char MesOut[8], char MesIn[8]) // 执行DES解密
{ // Hex输入 Bin运算 字节输出
	int i = 0;
	static bool MesBit[64] = { 0 }; // 密文二进制存储空间 64位
	static bool Temp[32] = { 0 };
	static bool* MiL = &MesBit[0], * MiR = &MesBit[32]; // 前32位 后32位
	HexToBit(MesBit, MesIn, 64); // 把密文换成二进制存入MesBit
	TablePermute(MesBit, MesBit, IP_Table, 64); // IP置换
	for (i = 15;i >= 0;i--)
	{
		BitsCopy(Temp, MiL, 32);
		F_Change(MiL, SubKey[i]);
		Xor(MiL, MiR, 32);
		BitsCopy(MiR, Temp, 32);
	}
	TablePermute(MesBit, MesBit, IPR_Table, 64);
	BitToByte(MesOut, MesBit, 64);
}